/*!
 * @file waterMenager.cpp
 * @brief Ciało waterMenager.hh
 */

#include "modes/world/water/waterMenager.hh"
using namespace std;

/*--------------------------------------------------------------------------*/

waterMenager::waterMenager() {

	this->waterShader = new shader("waterShader");
	this->waterShader->addShader("pawirr/shaders/water.v", ST_V);
	this->waterShader->addShader("pawirr/shaders/water.f", ST_F);

	glGenVertexArrays(1, &this->vao);
	glBindVertexArray(this->vao);

	point3f *water = new point3f[128 * 128 * 4];
	point3f *texc = new point3f[128 * 128 * 4];

	int nIndex = 0;
	float flX;
	float flZ;

	for (int hMapX = 0; hMapX < 128; hMapX++) {
		for (int hMapZ = 0; hMapZ < 128; hMapZ++) {
			for (int nTri = 0; nTri < 6; nTri++) {

				if (nTri == 3 || nTri == 4)
					continue;

				flX = (float) hMapX
						+ ((nTri == 1 || nTri == 2 || nTri == 4) ? 1 : 0);
				flZ = (float) hMapZ
						+ ((nTri == 2 || nTri == 4 || nTri == 5) ? 1 : 0);

				water[nIndex].x = flX;
				water[nIndex].y = 0;
				water[nIndex].z = flZ;

				texc[nIndex].x = (flX) / 128;
				texc[nIndex].y = (flZ) / 128;
				texc[nIndex].z = 0;

				nIndex++;
			}//for dla 6 wierzcholkow
		}//for dla z
	}//for dla x

	glGenBuffers(2, this->vbo);

	glBindBufferARB(GL_ARRAY_BUFFER, this->vbo[0]);
	glBufferDataARB(GL_ARRAY_BUFFER_ARB, 128 * 128 * 4 * sizeof(point3f),
			water, GL_STATIC_DRAW_ARB);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(point3f), NULL);

	delete[] water;

	glBindBufferARB(GL_ARRAY_BUFFER, this->vbo[1]);
	glBufferDataARB(GL_ARRAY_BUFFER_ARB, 128 * 128 * 4 * sizeof(point3f),
			texc, GL_STATIC_DRAW_ARB);

	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(point3f), NULL);

	delete[] texc;

	this->waterShader->addAttrib("attPos", 0);
	this->waterShader->addAttrib("attTex", 1);


	this->waterShader->linkProgram();

	pawirr::graphic->_env->addEnvUniforms(this->waterShader);

	this->waterShader->addUniformf(string("water_translation"),
			&this->translation.x, &this->translation.y);

	/*---------------*/
	this->tex1 = new texture("pawirr/textures/water/perlin1.png");
	this->waterShader->addTexture("tex_water1", this->tex1);
	/*---------------*/
	this->tex2 = new texture("pawirr/textures/water/perlin2.png");
	this->waterShader->addTexture("tex_water2", this->tex2);
	/*---------------*/
	this->reflectionTex = new texture(pawirr::graphic->resX/2,
			pawirr::graphic->resY/2);
	this->waterShader->addTexture("tex_reflection", this->reflectionTex);
	/*---------------*/
	this->underwaterTex = new texture(pawirr::graphic->resX,
			pawirr::graphic->resY);
	this->waterShader->addTexture("tex_underwater", this->underwaterTex);
	/*---------------*/
	this->waterShader->addTexture("tex_hmap", pawirr::m->world->_area->texturePack->texture_hmap);
	/*---------------*/
	glBindVertexArray(0);
}

/*--------------------------------------------------------------------------*/

void waterMenager::draw(water_drawMode dm) {
	point2f world = pawirr::m->world->_area->getWorldSize();

		for (int x = -1; x <= 1; ++x) {
			for (int y = -1; y <= 1; ++y) {
				this->drawSquare(point2f(x * world.x, y * world.y), dm);
			}
		}

		glCullFace(GL_FRONT);

		for (int x = -1; x <= 1; ++x) {
			for (int y = -1; y <= 1; ++y) {
				this->drawSquare(point2f(x * world.x, y * world.y), dm);
			}
		}

		glCullFace(GL_BACK);

}

/*--------------------------------------------------------------------------*/

void waterMenager::drawSquare(point2f pos, water_drawMode dm) {

	this->translation = pos;

	glPushMatrix();
	glTranslatef(pos.x, 0, pos.y);
	glScalef(8.0, 1.0, 8.0);

	this->waterShader->bind();

	glBindVertexArray(this->vao);

	GLuint var_location;

	//time
	if (var_location = glGetUniformLocation(this->waterShader->getProgram(),
			"time")) {
		glUniform1f(var_location, (float) pawirr::getTime());
	}
	if (var_location = glGetUniformLocation(this->waterShader->getProgram(),
			"waterDrawMode")) {

		if(dm == water_dm_all){
			glUniform1i(var_location, 1);
		}
		else if(dm == water_dm_godrays){
			glUniform1i(var_location, 0);
		}
	}

	glDrawArrays(GL_QUADS, 0, 128 * 128 * 4);

	this->waterShader->unbind();
	glPopMatrix();
}

/*--------------------------------------------------------------------------*/

texture *waterMenager::getReflectionTexture(){
	return this->reflectionTex;
}

/*--------------------------------------------------------------------------*/

texture *waterMenager::getUnderwaterTexture(){
	return this->underwaterTex;
}

/*--------------------------------------------------------------------------*/
